package com.basker.pisces.core.repository;

import java.util.List;

import com.basker.pisces.core.PageRowList;
import com.basker.pisces.core.RowContract;
import com.basker.pisces.core.exception.StaleObjectException;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.query.IQuery.PagingInfo;
import com.basker.pisces.core.query.QueryInfo;
import com.basker.pisces.core.query.meta.QueryMeta;
import com.basker.pisces.spring.SpringApplicationContext;

/**
 * 数据仓库接口
 *
 * @author hangwen
 */
public interface IDataRepository {
    /**
     * 获取IDataRepository的实例
     *
     * @return
     */
    public static IDataRepository getInstance() {
        return SpringApplicationContext.getInstance().getBean(IDataRepository.class);
    }

    /**
     * 对于指定的元数据，通过id删除
     *
     * @param objectMeta
     * @param id
     */
    void delete(IDataObjectMeta objectMeta, Object id);

    /**
     * 对于指定的元数据，通过id批量删除
     *
     * @param objectMeta
     * @param ids
     */
    void deleteBatch(IDataObjectMeta objectMeta, Object[] ids);

    /**
     * 填充外键字段的值
     *
     * @param objectMeta  对象元信息
     * @param dataObjects 待填充的对象
     */
    void fillReferenceFields(IDataObjectMeta objectMeta, Object[] dataObjects);

    /**
     * 对于指定的元数据,通过id加载数据
     *
     * @param objectMeta
     * @param id
     * @return
     */
    Object load(IDataObjectMeta objectMeta, Object id);

    /**
     * 对于指定的元数据,通过id批量加载数据
     *
     * @param objectMeta
     * @param ids
     * @return
     */
    Object[] loadBatch(IDataObjectMeta objectMeta, Object[] ids);

    /**
     * 对于指定的元数据，通过id批量加载数据，用于更新
     *
     * @param objectMeta
     * @param ids
     * @return
     */
    Object[] loadBatchForUpdate(IDataObjectMeta objectMeta, Object[] ids);

    /**
     * 对于指定的元数据,通过id加载数据，用于更新
     *
     * @param objectMeta
     * @param id
     * @return
     */
    Object loadForUpdate(IDataObjectMeta objectMeta, Object id);

    /**
     * 对于指定的元数据,通过sql条件查询数据
     *
     * @param objectMeta
     * @param whereSql
     * @param args
     * @return
     */
    Object[] query(IDataObjectMeta objectMeta, String whereSql, Object... args);

    /**
     * 对于指定的查询元数据和对应的查询信息,返回单个对象
     *
     * @param <T>
     * @param queryMeta
     * @param queryInfo
     * @param returnType
     * @return
     */
    <T> T queryForObject(QueryMeta queryMeta, QueryInfo queryInfo, Class<T> returnType);

    /**
     * 对于指定的查询元数据和对应的查询信息，进行分页查询，与查询业务对象不同，返回的数据为“数据行”的集合，“数据列”由queryInfo决定
     *
     * @param queryMeta
     * @param queryInfo
     * @param pagingInfo
     * @return
     */
    PageRowList queryForPageRows(QueryMeta queryMeta, QueryInfo queryInfo, PagingInfo pagingInfo);

    /**
     * 对于指定的查询元数据和对应的查询信息,返回符合条件数据的行数
     *
     * @param queryMeta
     * @param queryInfo
     * @return
     */
    int queryForRowCount(QueryMeta queryMeta, QueryInfo queryInfo);

    /**
     * 对于指定的查询元数据和对应的查询信息，进行列表查询，与查询业务对象不同，返回的数据为“数据行”的集合，“数据列”由queryInfo决定
     *
     * @param queryMeta
     * @param queryInfo
     * @return
     */
    List<RowContract> queryForRows(QueryMeta queryMeta, QueryInfo queryInfo);

    /**
     * 对于指定的元数据,通过sql条件查询数据,用于更新.
     *
     * <b>注意：在事务内，此方法慎用，因为数据库会锁定所有符合条件的记录，直到事务commit或rollback，建议按主键查询，这样数据库只会锁定当前行
     *
     * @param objectMeta
     * @param whereSql
     * @param args
     * @return
     */
    Object[] queryForUpdate(IDataObjectMeta objectMeta, String whereSql, Object... args);

    /**
     * 对于指定的元数据，保存一个对象
     *
     * @param objectMeta
     * @param dataObject
     * @return 如对象成功保存，返回其Id
     * @throws StaleObjectException
     */
    Object save(IDataObjectMeta objectMeta, Object dataObject) throws StaleObjectException;

    /**
     * 对于指定的元数据，批量保存对象
     *
     * @param objectMeta
     * @param dataObjects
     * @return 返回成功保存的对象Id
     * @throws StaleObjectException
     */
    Object[] saveBatch(IDataObjectMeta objectMeta, Object[] dataObjects) throws StaleObjectException;
}
